using System;
using System.Collections;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

namespace GameSystems
{
    /// <summary>
    /// 密码强度检查器 - 评估和验证密码强度
    /// </summary>
    public class PasswordStrengthChecker : MonoBehaviour
    {
        #region Enums

        /// <summary>
        /// 密码强度等级
        /// </summary>
        public enum PasswordStrength
        {
            VeryWeak,
            Weak,
            Fair,
            Good,
            Strong,
            VeryStrong
        }

        #endregion

        #region Events

        /// <summary>
        /// 密码强度改变事件
        /// </summary>
        [Serializable] public class PasswordStrengthChangedEvent : UnityEvent<PasswordStrength> { }

        /// <summary>
        /// 密码验证通过事件
        /// </summary>
        [Serializable] public class PasswordValidationPassedEvent : UnityEvent { }

        /// <summary>
        /// 密码验证失败事件
        /// </summary>
        [Serializable] public class PasswordValidationFailedEvent : UnityEvent<string> { }

        #endregion

        #region Serialized Fields

        [Header("密码强度配置")]
        [Tooltip("最小密码长度")]
        [SerializeField] private int minLength = 8;

        [Tooltip("最大密码长度")]
        [SerializeField] private int maxLength = 128;

        [Tooltip("是否要求包含大写字母")]
        [SerializeField] private bool requireUppercase = true;

        [Tooltip("是否要求包含小写字母")]
        [SerializeField] private bool requireLowercase = true;

        [Tooltip("是否要求包含数字")]
        [SerializeField] private bool requireNumbers = true;

        [Tooltip("是否要求包含特殊字符")]
        [SerializeField] private bool requireSpecialCharacters = true;

        [Tooltip("最少特殊字符数量")]
        [SerializeField] private int minSpecialCharacters = 1;

        [Header("常见密码检查")]
        [Tooltip("是否检查常见密码")]
        [SerializeField] private bool checkCommonPasswords = true;

        [Tooltip("常见密码列表")]
        [SerializeField] private string[] commonPasswords = {
            "password", "123456", "123456789", "qwerty", "abc123", "password123",
            "admin", "letmein", "welcome", "monkey", "1234567890", "password1"
        };

        [Header("密码强度评分")]
        [Tooltip("长度评分权重")]
        [Range(0, 1)]
        [SerializeField] private float lengthWeight = 0.3f;

        [Tooltip("字符多样性评分权重")]
        [Range(0, 1)]
        [SerializeField] private float diversityWeight = 0.4f;

        [Tooltip("模式识别评分权重")]
        [Range(0, 1)]
        [SerializeField] private float patternWeight = 0.3f;

        [Header("UI组件引用")]
        [Tooltip("密码输入框")]
        [SerializeField] private InputField passwordInputField;

        [Tooltip("确认密码输入框")]
        [SerializeField] private InputField confirmPasswordInputField;

        [Tooltip("强度指示器")]
        [SerializeField] private Slider strengthIndicator;

        [Tooltip("强度文本")]
        [SerializeField] private Text strengthText;

        [Tooltip("要求列表")]
        [SerializeField] private GameObject[] requirementIndicators;

        [Header("视觉反馈")]
        [Tooltip("非常弱颜色")]
        [SerializeField] private Color veryWeakColor = Color.red;

        [Tooltip("弱颜色")]
        [SerializeField] private Color weakColor = new Color(1f, 0.5f, 0f);

        [Tooltip("一般颜色")]
        [SerializeField] private Color fairColor = Color.yellow;

        [Tooltip("良好颜色")]
        [SerializeField] private Color goodColor = new Color(0.5f, 1f, 0f);

        [Tooltip("强颜色")]
        [SerializeField] private Color strongColor = Color.green;

        [Tooltip("非常强颜色")]
        [SerializeField] private Color veryStrongColor = new Color(0f, 0.5f, 0f);

        [Header("调试选项")]
        [Tooltip("是否启用调试日志")]
        [SerializeField] private bool enableDebugLogs = true;

        #endregion

        #region Events

        [Header("事件回调")]
        [Tooltip("密码强度改变时触发")]
        public PasswordStrengthChangedEvent OnPasswordStrengthChanged;

        [Tooltip("密码验证通过时触发")]
        public PasswordValidationPassedEvent OnPasswordValidationPassed;

        [Tooltip("密码验证失败时触发")]
        public PasswordValidationFailedEvent OnPasswordValidationFailed;

        #endregion

        #region Private Fields

        private PasswordStrength currentStrength = PasswordStrength.VeryWeak;
        private bool isPasswordValid = false;
        private Coroutine checkCoroutine;

        // 正则表达式模式
        private static readonly Regex UppercasePattern = new Regex("[A-Z]");
        private static readonly Regex LowercasePattern = new Regex("[a-z]");
        private static readonly Regex NumberPattern = new Regex("[0-9]");
        private static readonly Regex SpecialCharPattern = new Regex("[^a-zA-Z0-9]");
        private static readonly Regex RepeatingCharPattern = new Regex(@"(.)\1{2,}");
        private static readonly Regex SequentialCharPattern = new Regex(@"(?:abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz|012|123|234|345|456|567|678|789)", RegexOptions.IgnoreCase);

        #endregion

        #region Unity Lifecycle

        /// <summary>
        /// 初始化组件
        /// </summary>
        private void Awake()
        {
            InitializeUI();
            ValidateComponents();
        }

        /// <summary>
        /// 清理资源
        /// </summary>
        private void OnDestroy()
        {
            CleanupEvents();

            if (checkCoroutine != null)
            {
                StopCoroutine(checkCoroutine);
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// 检查密码强度
        /// </summary>
        /// <param name="password">密码</param>
        /// <returns>密码强度等级</returns>
        public PasswordStrength CheckPasswordStrength(string password)
        {
            if (string.IsNullOrEmpty(password))
            {
                return PasswordStrength.VeryWeak;
            }

            float score = CalculatePasswordScore(password);
            PasswordStrength strength = ScoreToStrength(score);

            // 更新当前强度
            if (currentStrength != strength)
            {
                currentStrength = strength;
                OnPasswordStrengthChanged?.Invoke(strength);
            }

            return strength;
        }

        /// <summary>
        /// 验证密码是否符合要求
        /// </summary>
        /// <param name="password">密码</param>
        /// <returns>验证结果</returns>
        public bool ValidatePassword(string password)
        {
            if (string.IsNullOrEmpty(password))
            {
                OnPasswordValidationFailed?.Invoke("密码不能为空");
                return false;
            }

            // 检查长度
            if (password.Length < minLength || password.Length > maxLength)
            {
                OnPasswordValidationFailed?.Invoke($"密码长度必须在{minLength}-{maxLength}个字符之间");
                return false;
            }

            // 检查字符要求
            if (requireUppercase && !UppercasePattern.IsMatch(password))
            {
                OnPasswordValidationFailed?.Invoke("密码必须包含至少一个大写字母");
                return false;
            }

            if (requireLowercase && !LowercasePattern.IsMatch(password))
            {
                OnPasswordValidationFailed?.Invoke("密码必须包含至少一个小写字母");
                return false;
            }

            if (requireNumbers && !NumberPattern.IsMatch(password))
            {
                OnPasswordValidationFailed?.Invoke("密码必须包含至少一个数字");
                return false;
            }

            if (requireSpecialCharacters)
            {
                MatchCollection matches = SpecialCharPattern.Matches(password);
                if (matches.Count < minSpecialCharacters)
                {
                    OnPasswordValidationFailed?.Invoke($"密码必须包含至少{minSpecialCharacters}个特殊字符");
                    return false;
                }
            }

            // 检查常见密码
            if (checkCommonPasswords && IsCommonPassword(password))
            {
                OnPasswordValidationFailed?.Invoke("密码过于常见，请选择更安全的密码");
                return false;
            }

            // 检查重复字符
            if (RepeatingCharPattern.IsMatch(password))
            {
                OnPasswordValidationFailed?.Invoke("密码不能包含连续重复的字符");
                return false;
            }

            // 检查连续字符
            if (SequentialCharPattern.IsMatch(password))
            {
                OnPasswordValidationFailed?.Invoke("密码不能包含连续的字符序列");
                return false;
            }

            isPasswordValid = true;
            OnPasswordValidationPassed?.Invoke();
            return true;
        }

        /// <summary>
        /// 验证密码确认
        /// </summary>
        /// <param name="password">密码</param>
        /// <param name="confirmPassword">确认密码</param>
        /// <returns>验证结果</returns>
        public bool ValidatePasswordConfirmation(string password, string confirmPassword)
        {
            if (string.IsNullOrEmpty(confirmPassword))
            {
                OnPasswordValidationFailed?.Invoke("请输入确认密码");
                return false;
            }

            if (password != confirmPassword)
            {
                OnPasswordValidationFailed?.Invoke("两次输入的密码不一致");
                return false;
            }

            return true;
        }

        /// <summary>
        /// 生成随机密码
        /// </summary>
        /// <param name="length">密码长度</param>
        /// <param name="includeUppercase">是否包含大写字母</param>
        /// <param name="includeLowercase">是否包含小写字母</param>
        /// <param name="includeNumbers">是否包含数字</param>
        /// <param name="includeSpecialChars">是否包含特殊字符</param>
        /// <returns>生成的密码</returns>
        public string GenerateRandomPassword(int length = 12, bool includeUppercase = true,
            bool includeLowercase = true, bool includeNumbers = true, bool includeSpecialChars = true)
        {
            if (length < minLength)
                length = minLength;

            string chars = "";
            if (includeUppercase) chars += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            if (includeLowercase) chars += "abcdefghijklmnopqrstuvwxyz";
            if (includeNumbers) chars += "0123456789";
            if (includeSpecialChars) chars += "!@#$%^&*()_+-=[]{}|;:,.<>?";

            if (string.IsNullOrEmpty(chars))
                chars = "abcdefghijklmnopqrstuvwxyz";

            string password = "";
            System.Random random = new System.Random();

            for (int i = 0; i < length; i++)
            {
                password += chars[random.Next(chars.Length)];
            }

            return password;
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// 计算密码评分
        /// </summary>
        private float CalculatePasswordScore(string password)
        {
            float lengthScore = CalculateLengthScore(password);
            float diversityScore = CalculateDiversityScore(password);
            float patternScore = CalculatePatternScore(password);

            float totalScore = (lengthScore * lengthWeight) +
                              (diversityScore * diversityWeight) +
                              (patternScore * patternWeight);

            return Mathf.Clamp01(totalScore);
        }

        /// <summary>
        /// 计算长度评分
        /// </summary>
        private float CalculateLengthScore(string password)
        {
            if (password.Length < minLength) return 0f;
            if (password.Length >= 20) return 1f;

            // 线性插值计算
            float normalizedLength = (float)(password.Length - minLength) / (20 - minLength);
            return Mathf.Clamp01(normalizedLength);
        }

        /// <summary>
        /// 计算字符多样性评分
        /// </summary>
        private float CalculateDiversityScore(string password)
        {
            int diversityTypes = 0;

            if (UppercasePattern.IsMatch(password)) diversityTypes++;
            if (LowercasePattern.IsMatch(password)) diversityTypes++;
            if (NumberPattern.IsMatch(password)) diversityTypes++;
            if (SpecialCharPattern.IsMatch(password)) diversityTypes++;

            return (float)diversityTypes / 4f;
        }

        /// <summary>
        /// 计算模式评分
        /// </summary>
        private float CalculatePatternScore(string password)
        {
            float score = 1f;

            // 检查重复字符
            if (RepeatingCharPattern.IsMatch(password))
                score -= 0.3f;

            // 检查连续字符
            if (SequentialCharPattern.IsMatch(password))
                score -= 0.3f;

            // 检查常见密码
            if (checkCommonPasswords && IsCommonPassword(password))
                score -= 0.5f;

            return Mathf.Clamp01(score);
        }

        /// <summary>
        /// 将评分转换为强度等级
        /// </summary>
        private PasswordStrength ScoreToStrength(float score)
        {
            if (score < 0.2f) return PasswordStrength.VeryWeak;
            if (score < 0.4f) return PasswordStrength.Weak;
            if (score < 0.6f) return PasswordStrength.Fair;
            if (score < 0.8f) return PasswordStrength.Good;
            if (score < 0.95f) return PasswordStrength.Strong;
            return PasswordStrength.VeryStrong;
        }

        /// <summary>
        /// 检查是否为常见密码
        /// </summary>
        private bool IsCommonPassword(string password)
        {
            string lowerPassword = password.ToLower();

            foreach (string commonPassword in commonPasswords)
            {
                if (lowerPassword.Contains(commonPassword))
                    return true;
            }

            return false;
        }

        /// <summary>
        /// 更新UI显示
        /// </summary>
        private void UpdateUI(string password)
        {
            // 更新强度指示器
            if (strengthIndicator != null)
            {
                strengthIndicator.value = (float)currentStrength / (float)PasswordStrength.VeryStrong;
                strengthIndicator.fillRect.GetComponent<Image>().color = GetStrengthColor(currentStrength);
            }

            // 更新强度文本
            if (strengthText != null)
            {
                strengthText.text = GetStrengthText(currentStrength);
                strengthText.color = GetStrengthColor(currentStrength);
            }

            // 更新要求指示器
            UpdateRequirementIndicators(password);
        }

        /// <summary>
        /// 更新要求指示器
        /// </summary>
        private void UpdateRequirementIndicators(string password)
        {
            if (requirementIndicators == null || requirementIndicators.Length == 0)
                return;

            int index = 0;

            // 检查长度要求
            if (index < requirementIndicators.Length)
            {
                bool met = password.Length >= minLength;
                requirementIndicators[index].SetActive(met);
                index++;
            }

            // 检查大写字母要求
            if (requireUppercase && index < requirementIndicators.Length)
            {
                bool met = UppercasePattern.IsMatch(password);
                requirementIndicators[index].SetActive(met);
                index++;
            }

            // 检查小写字母要求
            if (requireLowercase && index < requirementIndicators.Length)
            {
                bool met = LowercasePattern.IsMatch(password);
                requirementIndicators[index].SetActive(met);
                index++;
            }

            // 检查数字要求
            if (requireNumbers && index < requirementIndicators.Length)
            {
                bool met = NumberPattern.IsMatch(password);
                requirementIndicators[index].SetActive(met);
                index++;
            }

            // 检查特殊字符要求
            if (requireSpecialCharacters && index < requirementIndicators.Length)
            {
                MatchCollection matches = SpecialCharPattern.Matches(password);
                bool met = matches.Count >= minSpecialCharacters;
                requirementIndicators[index].SetActive(met);
                index++;
            }
        }

        /// <summary>
        /// 获取强度颜色
        /// </summary>
        private Color GetStrengthColor(PasswordStrength strength)
        {
            switch (strength)
            {
                case PasswordStrength.VeryWeak: return veryWeakColor;
                case PasswordStrength.Weak: return weakColor;
                case PasswordStrength.Fair: return fairColor;
                case PasswordStrength.Good: return goodColor;
                case PasswordStrength.Strong: return strongColor;
                case PasswordStrength.VeryStrong: return veryStrongColor;
                default: return Color.gray;
            }
        }

        /// <summary>
        /// 获取强度文本
        /// </summary>
        private string GetStrengthText(PasswordStrength strength)
        {
            switch (strength)
            {
                case PasswordStrength.VeryWeak: return "非常弱";
                case PasswordStrength.Weak: return "弱";
                case PasswordStrength.Fair: return "一般";
                case PasswordStrength.Good: return "良好";
                case PasswordStrength.Strong: return "强";
                case PasswordStrength.VeryStrong: return "非常强";
                default: return "未知";
            }
        }

        /// <summary>
        /// 初始化UI
        /// </summary>
        private void InitializeUI()
        {
            if (passwordInputField != null)
            {
                passwordInputField.onValueChanged.AddListener(OnPasswordChanged);
            }

            if (confirmPasswordInputField != null)
            {
                confirmPasswordInputField.onValueChanged.AddListener(OnConfirmPasswordChanged);
            }
        }

        /// <summary>
        /// 密码输入改变回调
        /// </summary>
        private void OnPasswordChanged(string password)
        {
            if (checkCoroutine != null)
            {
                StopCoroutine(checkCoroutine);
            }

            checkCoroutine = StartCoroutine(DelayedPasswordCheck(password));
        }

        /// <summary>
        /// 确认密码输入改变回调
        /// </summary>
        private void OnConfirmPasswordChanged(string confirmPassword)
        {
            if (passwordInputField != null && !string.IsNullOrEmpty(confirmPassword))
            {
                ValidatePasswordConfirmation(passwordInputField.text, confirmPassword);
            }
        }

        /// <summary>
        /// 延迟密码检查协程
        /// </summary>
        private IEnumerator DelayedPasswordCheck(string password)
        {
            yield return new WaitForSeconds(0.3f);

            CheckPasswordStrength(password);
            UpdateUI(password);
        }

        /// <summary>
        /// 验证组件
        /// </summary>
        private void ValidateComponents()
        {
            if (passwordInputField == null)
                LogWarning("密码输入框未设置");
            if (strengthIndicator == null)
                LogWarning("强度指示器未设置");
            if (strengthText == null)
                LogWarning("强度文本未设置");
        }

        /// <summary>
        /// 清理事件
        /// </summary>
        private void CleanupEvents()
        {
            if (passwordInputField != null)
            {
                passwordInputField.onValueChanged.RemoveListener(OnPasswordChanged);
            }

            if (confirmPasswordInputField != null)
            {
                confirmPasswordInputField.onValueChanged.RemoveListener(OnConfirmPasswordChanged);
            }
        }

        #endregion

        #region Debug Methods

        /// <summary>
        /// 调试日志
        /// </summary>
        private void LogDebug(string message)
        {
            if (enableDebugLogs)
                Debug.Log($"[PasswordStrengthChecker] {message}");
        }

        /// <summary>
        /// 警告日志
        /// </summary>
        private void LogWarning(string message)
        {
            if (enableDebugLogs)
                Debug.LogWarning($"[PasswordStrengthChecker] {message}");
        }

        /// <summary>
        /// 错误日志
        /// </summary>
        private void LogError(string message)
        {
            if (enableDebugLogs)
                Debug.LogError($"[PasswordStrengthChecker] {message}");
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// 当前密码强度
        /// </summary>
        public PasswordStrength CurrentStrength => currentStrength;

        /// <summary>
        /// 密码是否有效
        /// </summary>
        public bool IsPasswordValid => isPasswordValid;

        /// <summary>
        /// 最小密码长度
        /// </summary>
        public int MinLength
        {
            get => minLength;
            set => minLength = Mathf.Max(1, value);
        }

        /// <summary>
        /// 最大密码长度
        /// </summary>
        public int MaxLength
        {
            get => maxLength;
            set => maxLength = Mathf.Max(minLength, value);
        }

        #endregion
    }
}
